package ink.xiaobaibai.config;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import ink.xiaobaibai.controller.DeviceLogController;
import ink.xiaobaibai.entity.*;
import ink.xiaobaibai.enumOxy.DeviceStatus;
import ink.xiaobaibai.enumOxy.FaultStatus;
import ink.xiaobaibai.enumOxy.MonthlyDeviceStatus;
import ink.xiaobaibai.enumOxy.MonthlyfeeOrderStatus;
import ink.xiaobaibai.service.*;
import ink.xiaobaibai.serviceOxy.IMqttService;
import ink.xiaobaibai.serviceOxy.ISmsService;
import ink.xiaobaibai.serviceOxy.onePay.IUploadService;
import javafx.util.Pair;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @description: 定时任务配置类
 * @author: 小白白
 * @create: 2021-05-29
 **/

@Configuration
@EnableScheduling
public class SchedulingConfig {

    @Autowired
    private IReportClientOrderService reportClientOrderService;

    @Autowired
    private IMonthlyfeeOrderService monthlyfeeOrderService;

    @Autowired
    private IMonthlyUserDeviceService userDeviceService;

    @Autowired
    private IDeviceLogService deviceLogService;

    @Autowired
    private ICouponService couponService;

    @Autowired
    private ICouponUserService couponUserService;

    @Autowired
    private IUploadService uploadService;

    @Autowired
    private IOzoneDeviceService ozoneDeviceService;

    @Autowired
    private IOxygenDeviceService oxygenDeviceService;

    @Autowired
    private IFaultDeviceService faultDeviceService;

    @Autowired
    private IFaultTerminalService faultTerminalService;

    @Autowired
    private ICouponCodeService couponCodeService;

    @Autowired
    private ICouponCodeLogService couponCodeLogService;

    @Autowired
    private IMonthlyUserDeviceService monthlyUserDeviceService;

    @Autowired
    private IMonthlyfeeDeviceService monthlyfeeDeviceService;

    @Autowired
    private IMqttService mqttService;

    @Autowired
    private ISmsService smsService;

    private int checkPageNum = 1;

    /**
     * 每个月一号的凌晨3点半执行自动生成上月报表
     */
    @Scheduled(cron = "0 30 3 1 * ?")
//    @Scheduled(cron = "50 40 18 * * ?")
    private void autoGenerateReport() {
        //自动生成三个业务的报表
        this.reportClientOrderService.autoGenerateReportOrder();

        //清除6个月之前的机器日志
        QueryWrapper<DeviceLog> q1 = new QueryWrapper<>();
        q1.le("create_time", DateUtils.addDays(new Date(), -180));
        this.deviceLogService.remove(q1);

        //6个月前的优惠券记录
        QueryWrapper<CouponUser> q2 = new QueryWrapper<>();
        q2.le("create_time", DateUtils.addDays(new Date(), -180));
        this.couponUserService.remove(q2);

        //已经失效3个月的优惠券
        QueryWrapper<Coupon> q3 = new QueryWrapper<>();
        q3.le("deadline", DateUtils.addDays(new Date(), -90));
        this.couponService.remove(q3);

        QueryWrapper<FaultDevice> q4 = new QueryWrapper<>();
        q4.eq("status", FaultStatus.PROCESSED.getStatus());
        q4.le("create_time", DateUtils.addDays(new Date(), -90));
        this.faultDeviceService.remove(q4);

        QueryWrapper<FaultTerminal> q5 = new QueryWrapper<>();
        q5.eq("status", FaultStatus.PROCESSED.getStatus());
        q5.le("create_time", DateUtils.addDays(new Date(), -90));
        this.faultTerminalService.remove(q5);

        QueryWrapper<CouponCode> q6 = new QueryWrapper<>();
        q6.le("expires_time", DateUtils.addDays(new Date(), -90));
        this.couponCodeService.remove(q6);

        QueryWrapper<CouponCodeLog> q7 = new QueryWrapper<>();
        q7.le("create_time", DateUtils.addDays(new Date(), -90));
        this.couponCodeLogService.remove(q7);

        System.out.println("完成月初任务");
    }

    /**
     * 每天的23:30分开始查验当前的monthly_order的状态是否已经过期
     */
    @Scheduled(cron = "0 30 23 * * ?")
    private void autoCheckMonthly() {
        QueryWrapper<MonthlyfeeOrder> q1 = new QueryWrapper<>();
        q1.select("order_id", "device_id", "expire_time", "status", "deposit_id");
        q1.eq("status", MonthlyfeeOrderStatus.INUSE.getStatus());
        q1.le("expire_time", new Date());
        List<MonthlyfeeOrder> list = this.monthlyfeeOrderService.list(q1);
        List<Integer> deviceIds = new ArrayList<>();
//        Date date=DateUtils.addMinutes(new Date(),40);
        for (MonthlyfeeOrder order : list) {
//            if(order.getExpireTime().getTime()<date.getTime()){
            //设置为已过期
            order.setStatus(MonthlyfeeOrderStatus.EXPIRED.getStatus());
            deviceIds.add(order.getDeviceId());
//            }
            // 减少IO
            order.setDeviceId(null);
            order.setExpireTime(null);
        }
        this.monthlyfeeOrderService.updateBatchById(list);
        UpdateWrapper<MonthlyUserDevice> u1 = new UpdateWrapper<>();
        u1.set("can_use", false);
//        u1.set("device_open",false);
        u1.in("device_id", deviceIds);
        if (deviceIds.size() != 0) {
            this.userDeviceService.update(u1);
        }
        // TODO 如果是供应商的订单,那么要和退款回调的执行看齐
        for (MonthlyfeeOrder order : list) {
            if (order.getDepositId() == null) {
                // 供应商的订单
                this.spHandler(order.getOrderId());
            }
        }
    }

    private void spHandler(String monOrderId) {
        //订单表
        QueryWrapper<MonthlyfeeOrder> q3 = new QueryWrapper<>();
        q3.select("order_id", "device_id");
        q3.eq("order_id", monOrderId);
        MonthlyfeeOrder mOrder = this.monthlyfeeOrderService.getOne(q3);
        mOrder.setStatus(MonthlyfeeOrderStatus.COMPLETED.getStatus());
        this.monthlyfeeOrderService.updateById(mOrder);
        //机器用户映射表
        QueryWrapper<MonthlyUserDevice> q4 = new QueryWrapper<>();
        q4.eq("device_id", mOrder.getDeviceId());
        this.userDeviceService.remove(q4);
        //机器表
        UpdateWrapper<MonthlyfeeDevice> u1 = new UpdateWrapper<>();
        u1.set("status", MonthlyDeviceStatus.FREE.getStatus());
        u1.eq("id", mOrder.getDeviceId());
        this.monthlyfeeDeviceService.update(u1);
    }

    // 凌晨2点16分 3天内机器快到期了短信每天都发送
    @Scheduled(cron = "0 16 2 * * ?")
    public void monDueReminder() {

        QueryWrapper<MonthlyfeeOrder> q1 = new QueryWrapper<>();
        q1.select("order_id", "admin_user_id", "user_id", "device_id", "expire_time");
        q1.eq("status", MonthlyfeeOrderStatus.INUSE.getStatus());
        q1.le("expire_time", DateUtils.addDays(new Date(), -3));
        List<MonthlyfeeOrder> list = this.monthlyfeeOrderService.list(q1);
        for (MonthlyfeeOrder order : list) {
            this.smsService.monDueReminder(order.getOrderId(), order.getAdminUserId(), order.getUserId(), order.getDeviceId(), order.getExpireTime());
        }

    }

    //三点半0秒
    @Scheduled(cron = "0 30 3 * * ?")
    private void op1() {

        //凌晨三点半 七牛云缓存的机器日志一天后删除 在DeviceLogController层中的set,clear并清除七牛云文件
        for (Pair<String, String> pair : DeviceLogController.fileUrlSet) {
            this.uploadService.deleteFile(pair.getKey());
        }
        DeviceLogController.fileUrlSet.clear();

    }

    /**
     * 冷淡时间的第四十五分钟,开始随机选择定点业务的[空闲]状态的机器,去心跳一下它
     * TODO 生产模式记得打开
     */
//    @Scheduled(cron = "0 45 1,2,3,4,5,6,7,8,22,23 * * ? ")
    private void op2() {

        // 使用limit一次查15个
        int itemCount = 15;

        int count = this.ozoneDeviceService.count();
        if (count == 0) {
            return;
        }
        if ((this.checkPageNum - 1) * itemCount >= count) {
            this.checkPageNum = 1;
        }
        QueryWrapper<OzoneDevice> q1 = new QueryWrapper<>();
        q1.select("device_code");
        q1.in("status", DeviceStatus.FREE.getStatus(), DeviceStatus.INUSE.getStatus());
        Page<OzoneDevice> page = this.ozoneDeviceService.page(new Page<>(this.checkPageNum, itemCount, false), q1);

        List<OzoneDevice> deviceList = page.getRecords();
        for (OzoneDevice ozoneDevice : deviceList) {
            // 内部自动发短信(也会自动查其对应的氧气机)
            this.mqttService.checkOnePayDevice(ozoneDevice.getDeviceCode());
        }

        this.checkPageNum++;
    }

}
